﻿using Face8280WebSocketServer.DB;
using Face8280WebSocketServer.DB.Device;
using Face8280WebSocketServer.DB.TimeGroup;
using Face8280WebSocketServer.DTO;
using Face8280WebSocketServer.Interface;
using Face8280WebSocketServer.Utility.ExpressionExtend;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace Face8280WebSocketServer.Service
{
    /// <summary>
    /// 设备远程操作服务
    /// </summary>
    public class DeviceRemoteService : BaseService, IDeviceRemoteService
    {
        private static Dictionary<string, int> gRemoteTable;
        private ICacheService _Cache;
        private IFaceDriveService _DriveDB;

        static DeviceRemoteService()
        {
            gRemoteTable = new Dictionary<string, int>();
            gRemoteTable.Add("opendoor", 1);//1，远程开门；2、远程重启；3、恢复出厂设置；4、关闭报警；5、清空所有人员
            gRemoteTable.Add("restart", 2);
            gRemoteTable.Add("reset", 3);
            gRemoteTable.Add("closealarm", 4);
            gRemoteTable.Add("emptyPeople", 5);
            gRemoteTable.Add("null", 0);
        }

        public DeviceRemoteService(DbContext context, ICacheService cache, IFaceDriveService driveDB) : base(context)
        {
            _Cache = cache;
            _DriveDB = driveDB;
        }

        public void Add(List<int> oDevicesIDs, string sRemote)
        {

            //需要刷新缓存的设备列表
            HashSet<int> deviceIDs = new HashSet<int>();

            var db = Context.Set<RemoteTaskDetail>();
            int iRemote = gRemoteTable[sRemote];
            foreach (var iDeviceID in oDevicesIDs)
            {
                var dtl = new RemoteTaskDetail()
                {
                    DeviceID = iDeviceID,
                    TaskType = iRemote
                };
                if (!deviceIDs.Contains(iDeviceID)) deviceIDs.Add(iDeviceID);

                AddUserLog("设备远程操作", $"新增设备远程操作任务： 详情：{dtl.ToJson()}");
                db.Add(dtl);
            }
            this.Commit();



            UpdateCache(deviceIDs);

        }


        public void ClearRemote()
        {
            Excute("Delete from RemoteTask");
            AddUserLog("设备远程操作", "清空所有设备远程操作记录");
            Commit();

            var query = from device in Set<FaceDeviceDetail>()
                        select device.DeviceID;
            var dic = new Dictionary<string, int>();
            foreach (var item in query)
            {
                dic.Add(item, 0);
            }
            query = null;

            _Cache.UpdateDeviceRemoteCache(dic);
        }

        public void Delete(List<int> taskIDs)
        {
            var db = Context.Set<RemoteTaskDetail>();
            //查询需要删除的设备
            HashSet<int> taskIDLists = new HashSet<int>(taskIDs);
            //需要刷新缓存的设备列表
            HashSet<int> deviceIDs = new HashSet<int>();

            var tasks = db.Where(x => taskIDLists.Contains(x.TaskID));
            foreach (var item in tasks)
            {
                AddUserLog("设备远程操作", $"删除设备远程操作任务： 详情：{item.ToJson()}");
                if (!deviceIDs.Contains(item.DeviceID)) deviceIDs.Add(item.DeviceID);
                db.Remove(item);
            }
            Commit();

            UpdateCache(deviceIDs);
        }
        /// <summary>
        /// 需要更新的设备ID
        /// </summary>
        /// <param name="deviceIDs"></param>
        private void UpdateCache(HashSet<int> deviceIDs)
        {
            var dic = new Dictionary<string, int>();

            //加载所有待上传任务，并分组统计
            var query = from device in Set<FaceDeviceDetail>()
                        join dTask in Set<RemoteTaskDetail>()
                        on device.ID equals dTask.DeviceID
                        where deviceIDs.Contains(device.ID) && dTask.TaskStatus == 0 && dTask.TaskType != 5
                        group device by device.DeviceID into groupedItems
                        select new { SN = groupedItems.Key, Count = groupedItems.Count() };

            foreach (var totalitem in query)
            {
                dic.Add(totalitem.SN, totalitem.Count);
            }
            if (deviceIDs.Count != dic.Count)
            {
                //有为0的项
                var dquery = from device in Set<FaceDeviceDetail>()
                             where deviceIDs.Contains(device.ID)
                             select new { device.ID, device.DeviceID };
                foreach (var item in dquery)
                {
                    if (!dic.ContainsKey(item.DeviceID))
                    {
                        dic.Add(item.DeviceID, 0);
                    }
                }
            }
            query = null;

            _Cache.UpdateDeviceRemoteCache(dic);


            dic.Clear();
            //记载所有清空人员记录
            query = from device in Set<FaceDeviceDetail>()
                        join dTask in Set<RemoteTaskDetail>()
                        on device.ID equals dTask.DeviceID
                        where deviceIDs.Contains(device.ID) && dTask.TaskStatus == 0 && dTask.TaskType == 5
                        group device by device.DeviceID into groupedItems
                        select new { SN = groupedItems.Key, Count = groupedItems.Count() };

            foreach (var totalitem in query)
            {
                dic.Add(totalitem.SN, totalitem.Count);
            }
            if (deviceIDs.Count != dic.Count)
            {
                //有为0的项
                var dquery = from device in Set<FaceDeviceDetail>()
                             where deviceIDs.Contains(device.ID)
                             select new { device.ID, device.DeviceID };
                foreach (var item in dquery)
                {
                    if (!dic.ContainsKey(item.DeviceID))
                    {
                        dic.Add(item.DeviceID, 0);
                    }
                }
            }
            query = null;

            _Cache.UpdateDeviceEmptyPeopleCache(dic);
        }


        public PageResult<RemoteTaskDetail_DTO> GetList(string sn, string name, string remote, BasePageParameter pagePar)
        {
            var query = from device in Set<FaceDeviceDetail>()
                        join dRemote in Set<RemoteTaskDetail>()
                        on device.ID equals dRemote.DeviceID
                        select new RemoteTaskDetail_DTO
                        {
                            TaskID = dRemote.TaskID,
                            //DeviceID = dRemote.DeviceID,
                            TaskType = dRemote.TaskType,
                            TaskStatus = dRemote.TaskStatus,
                            TaskRunTime = dRemote.TaskRunTime,
                            CreateTime = dRemote.CreateTime,
                            //LastUpdatetime = dRemote.LastUpdatetime,
                            DeviceName = device.DeviceName,
                            DeviceSN = device.DeviceID
                        };

            #region 组装查询条件
            List<Expression<Func<RemoteTaskDetail_DTO, bool>>> oWheres = new();
            if (!string.IsNullOrWhiteSpace(sn)) oWheres.Add(x => x.DeviceSN.Contains(sn));
            if (!string.IsNullOrWhiteSpace(name)) oWheres.Add(x => x.DeviceName.Contains(name));

            if (!string.IsNullOrWhiteSpace(remote) && remote != "null")
            {
                int iTaskType = gRemoteTable[remote];
                if (iTaskType > 0) oWheres.Add(x => x.TaskType == iTaskType);
            }


            Expression<Func<RemoteTaskDetail_DTO, bool>> oWhere = null;
            if (oWheres.Count > 0)
            {
                oWhere = oWheres[0];
                for (int i = 1; i < oWheres.Count; i++)
                {
                    oWhere = oWhere.And(oWheres[i]);
                }
            }
            if (oWhere != null)
                query = query.Where(oWhere);
            if (pagePar.isAsc)
                query = query.OrderBy(x => x.CreateTime);
            else
                query = query.OrderByDescending(x => x.CreateTime);

            #endregion

            PageResult<RemoteTaskDetail_DTO> result = new PageResult<RemoteTaskDetail_DTO>()
            {
                DataList = query.Skip((pagePar.pageIndex - 1) * pagePar.pageSize).Take(pagePar.pageSize).ToList(),
                PageIndex = pagePar.pageIndex,
                PageSize = pagePar.pageSize,
                TotalCount = query.Count()
            };
            return result;

        }

        public List<RemoteTaskDetail> GetRemoteTaskByDeviceID(int iDeviceID)
        {
            return Query<RemoteTaskDetail>(x => x.DeviceID == iDeviceID && x.TaskStatus == 0 && x.TaskType != 5)
                .Take(1).ToList();
        }

        public void UpdateTaskRunStatusComplete(int iDeviceID, int iTaskType)
        {
            var lst = Query<RemoteTaskDetail>(x => x.DeviceID == iDeviceID && x.TaskStatus == 0 && x.TaskType == iTaskType);
            foreach (var detail in lst)
            {
                detail.TaskStatus = 1;
                detail.TaskRunTime = System.DateTime.Now;

                AddUserLog("设备远程操作", $"执行远程操作任务： 详情：{detail.ToJson()}");
                //Update<RemoteTaskDetail>(detail);
            }

            this.Commit();

            if (iTaskType == 3)//设备恢复出厂设备，重置所有权限和门禁参数
            {


                var deviceDetail = Find<FaceDeviceDetail>(iDeviceID);

                AddUserLog("设备远程操作", $"设备执行恢复出厂操作： 详情：{deviceDetail.DeviceName}({deviceDetail.DeviceID})");


                _DriveDB.FormatDevice(iDeviceID);


            }
            else
            {
                UpdateCache(new HashSet<int>(new int[] { iDeviceID }));
            }



        }
    }
}
